import store from '@/store'
import NProgress from 'nprogress' // progress bar
import { ACCESS_TOKEN } from '@/store/mutation-types'
import storage from 'store'
import { debounce } from '@/utils/lodashChunk'
import { domTitle, setDocumentTitle } from '@/utils/domUtil'
// 无权限校验时引入路由表
import { routes } from './index'

export const allowList = [
  'Redirect',
  'user',
  'user-login',
  'exception',
  'exception-Exception403',
  'exception-Exception404',
  'exception-Exception500',
  '404'
]

const loginRoutePath = '/user/login'
const defaultRoutePath = '/dashboard'

// 是否需要从后端获取菜单
const isGetMenus = debounce(
  ({ to, from, next, router }) => {
    const roles = store.getters.roles
    /**
     * 获取菜单 - 暂无动态获取权限菜单
     */
    store
      .dispatch('permission/setRouters', { routes: routes, roles: roles })
      .then(() => {
        const hasRoutePermission = checkHasRoutePermission(to.name)
        if (hasRoutePermission) {
          // 请求带有 redirect 重定向时，登录自动重定向到该地址
          const redirect = decodeURIComponent(from.query.redirect || '')
          if (to.path === redirect || !redirect) {
            next({ ...to, replace: true })
          } else {
            // 跳转到目的路由
            next({ path: redirect, replace: true })
          }
        } else {
          // 在免登录名单，直接进入
          if (allowList.includes(to.name)) {
            next()
          } else {
            // 没有权限 跳转 403
            next({ path: '/exception/403', replace: true })
          }
          NProgress.done()
        }
      })
      .catch(() => next({ path: defaultRoutePath }))
  },
  1800,
  { leading: true }
)

// 校验当前路由是否存在
export function checkHasRoutePermission(_name) {
  const routes = store.getters.menus
  function hasRoute(_routes) {
    return _routes.some(item => {
      if (item.name === _name) {
        return true
      } else if (Array.isArray(item.children) && item.children.length) {
        return hasRoute(item.children)
      } else {
        return false
      }
    })
  }
  return hasRoute(routes)
}

// 创建路由守卫
export function createRouterGuards(router) {
  router.beforeEach(async (to, from, next) => {
    NProgress.start() // start progress bar
    // 清除遗留请求
    await store.dispatch('app/clearCancel')
    // 校验 token
    const token = storage.get(ACCESS_TOKEN)
    if (token) {
      // 判断用户信息是否存在
      if (!store.getters.userInfo.id) {
        // 获取用户信息
        await store.dispatch('user/GetInfo')
        // 重置菜单
        await store.dispatch('permission/setRouters')
        // 获取权限列表
        await store.dispatch('user/setRoles')
      }
      if (to.name === 'user-login') {
        next({ path: defaultRoutePath })
        NProgress.done()
      } else {
        if (store.getters.menus.length === 0) {
          // 防抖获取菜单
          isGetMenus({ to, from, next, router })
        } else {
          const hasRoutePermission = checkHasRoutePermission(to.name)
          if (allowList.includes(to.name) || hasRoutePermission) {
            return next()
          } else {
            next({ path: '/exception/403', replace: true })
            NProgress.done()
          }
        }
      }
    } else {
      // not login
      if (allowList.includes(to.name)) {
        // 在免登录名单，直接进入
        next()
      } else {
        next({ path: loginRoutePath, query: { redirect: to.fullPath }, replace: true })
        NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
      }
    }
  })

  router.afterEach((to, from, failure) => {
    // 设置网页标题
    to.meta && typeof to.meta.title !== 'undefined' && setDocumentTitle(`${to.meta.title} - ${domTitle}`)
    // 在这里设置需要缓存的组件名称
    const keepAliveComponents = store.state.permission.keepAliveComponents
    const currentComName = to.matched.find(item => item.name == to.name)?.components?.default.name
    if (currentComName && !keepAliveComponents.includes(currentComName) && to.meta?.keepAlive) {
      // 需要缓存的组件
      keepAliveComponents.push(currentComName)
    } else if (!to.meta?.keepAlive || to.name == 'Redirect') {
      // 不需要缓存的组件
      const index = store.state.permission.keepAliveComponents.findIndex(name => name == currentComName)
      if (index != -1) {
        keepAliveComponents.splice(index, 1)
      }
    }
    store.dispatch('permission/setkeepAliveComponents', keepAliveComponents)
    NProgress.done() // finish progress bar
  })

  router.onError(error => {
    console.log(error, '路由错误')
  })

  return router
}
